﻿using System;
using System.Collections.Generic;
using System.ServiceModel;
using System.ServiceModel.Channels;
using Needle.Bus.Transport.Impl.WCF.Hosts;

namespace Needle.Bus.Transport.Impl.WCF
{
    public class WCFTransport : CommunicationObject, ITransport
    {
    
        public WCFTransport()
        {
            _Extensions = new ExtensionCollection<ITransport>(this, ThisLock);
        }

        #region ITransport Members

        public IChannel<T> OpenChannel<T>(string channelName)
        {
            foreach (IChannel<T> channel in Extensions.FindAll<WCFChannel<T>>())
                if (channel.Topic == channelName)
                    return channel;

            var wcfChannel = new WCFChannel<T>(channelName);
            Extensions.Add(wcfChannel);
            return wcfChannel;
        }

        public void RegisterEndPoint<T>(IEndPoint<T> endPoint)
        {
            
            var wcfEndPoint = (WCFEndPoint<T>)null;
            var wcfEndPoints = Extensions.FindAll<WCFEndPoint<T>>();

            foreach (var ep in wcfEndPoints)
            {
                if (ep.Topic == endPoint.Topic)
                {
                    wcfEndPoint = ep;
                    break;
                }
            }

            if (wcfEndPoint == null)
            {
                var host = new WCFSingletonServiceHost<T>(endPoint.Topic);
                Extensions.Add(host.Singleton);
                hosts.Add(host);
                host.Open();
            }
            Extensions.Add(endPoint);
        }

        List<ServiceHostBase> hosts = new List<ServiceHostBase>();

        public void UnregisterEndPoint<T>(IEndPoint<T> endPoint)
        {
            Extensions.Remove(endPoint);
        }
        #endregion

        #region IExtensibleObject<ITransport> Members

        private ExtensionCollection<ITransport> _Extensions;
        public IExtensionCollection<ITransport> Extensions
        {
            get { return _Extensions; }
        }

        #endregion

        protected override TimeSpan DefaultCloseTimeout
        {
            get { return TimeSpan.FromMinutes(1); }
        }

        protected override TimeSpan DefaultOpenTimeout
        {
            get { return TimeSpan.FromMinutes(1); }
        }

        protected override void OnAbort()
        {
            
        }

        protected override IAsyncResult OnBeginClose(TimeSpan timeout, AsyncCallback callback, object state)
        {
            return null;
        }

        protected override IAsyncResult OnBeginOpen(TimeSpan timeout, AsyncCallback callback, object state)
        {
            return null; 
        }

        protected override void OnClose(TimeSpan timeout)
        {
            Extensions.Clear();
            foreach (var host in hosts)
            {
                try
                {
                    host.Close();
                }
                catch (Exception)
                { /*  */ }
            }
        }

        protected override void OnEndClose(IAsyncResult result)
        {
            
        }

        protected override void OnEndOpen(IAsyncResult result)
        {
            
        }

        protected override void OnOpen(TimeSpan timeout)
        {
            
        }
    }
}
